package com.request.invoke;

import com.alibaba.fastjson.JSONObject;
import com.request.annotation.MappingPrefix;
import com.request.parse.RequestParamParser;
import com.request.strategy.ParamProcessorStrategyFactory;
import com.request.strategy.RequestParamTypeProcess;
import com.rlyy.common.param.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * 请求代理
 *
 * @author yuanqinglong
 * @since 2021/10/18 11:30
 */
@Component
public class RequestProxyInvokeHandler implements InvocationHandler {


    @Autowired
    private SendRequestPostProcess sendRequestPostProcess;


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        }
        Request request = new Request();
        JSONObject requestData = new JSONObject();
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < method.getParameters().length; i++) {
            Parameter parameter = parameters[i];
            for (Annotation annotation : parameter.getAnnotations()) {
                RequestParamTypeProcess requestParamTypeProcessor = ParamProcessorStrategyFactory.getRequestParamTypeProcessor(annotation.annotationType());
                requestParamTypeProcessor.process(requestData, annotation, args[i]);
            }
        }
        String apiPrefix = this.apiPrefix(method);
        String api = RequestParamParser.getRequestMappingValue(method.getAnnotation(RequestMapping.class));
        request.setApiId(apiPrefix + api);
        request.setData(requestData);
        return sendRequestPostProcess.sendRequest(request);
    }


    /**
     * api的前缀
     *
     * @param method 方法
     * @return {@link String}
     * @throws Exception 异常
     */
    private String apiPrefix(Method method) throws Exception {
        if (method.getDeclaringClass().isAnnotationPresent(MappingPrefix.class)) {
            MappingPrefix requestMapping = method.getDeclaringClass().getAnnotation(MappingPrefix.class);
            return requestMapping.value();
        }
        return "";
    }


}
